package soar.test.file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.time.Instant;
import java.util.ArrayList;

public class App
{
    public static void main(String[] args)
    {
        System.exit(new App().run());
    }

    private String output_dir = "_output";

    private int run()
    {
        System.out.println("begin");

        try
        {
            final String split = "============================================================";

            System.out.println(split);

            init_dir(output_dir);

            copy_from_resources();
            System.out.println(split);

            // 文本
            text();
            System.out.println(split);

            // 流
            stream();
            System.out.println(split);

            performance();
            System.out.println(split);
        }
        catch (Exception e)
        {
            System.out.println(String.format("fail, %s", e));
            return 1;
        }

        System.out.println("end");

        return 0;
    }

    private void init_dir(String dir) throws Exception
    {
        File d = new File(dir);
        if (d.exists())
        {
            if (!d.isDirectory() || !d.canRead() || !d.canWrite()
                    || !d.canExecute())
            {
                throw new Exception(String.format("dir:%s invalid", dir));
            }
        }
        else
        {
            if (!d.mkdir())
            {
                throw new Exception(String.format("dir:%s create fail", dir));
            }
        }
    }

    private void copy_from_resources() throws Exception
    {
        System.out.println("copy_from_resources");
        System.out.println();

        String file_name;

        file_name = "test.jpg";
        InputStream file_in = Object.class.getResourceAsStream("/" + file_name);
        if (file_in == null)
        {
            System.out.println(String.format("/%s not found", file_name));
            return;
        }
        FileOutputStream file_out = new FileOutputStream(
                new File(output_dir + "/" + file_name));
        byte[] buf = new byte[1024];
        int len;
        while ((len = file_in.read(buf)) > 0)
        {
            file_out.write(buf, 0, len);
        }
        file_out.close();
        file_in.close();

        file_name = "test.xml";
        URL file_url = this.getClass().getResource("/" + file_name);
        System.out.println(
                String.format("URL.toString: %s", file_url.toString()));
        System.out
                .println(String.format("URL.getPath: %s", file_url.getPath()));
        System.out
                .println(String.format("URL.getFile: %s", file_url.getFile()));
        System.out.println(String.format("URL.toURI: %s", file_url.toURI()));
        file_in = this.getClass().getResourceAsStream("/" + file_name);
        file_out = new FileOutputStream(new File(output_dir + "/" + file_name));
        buf = new byte[file_in.available()];
        file_in.read(buf);
        file_out.write(buf);
        file_out.close();
        file_in.close();
        // String content=new String(buf);
        // System.out.println(content);

        file_name = "test.zero";
        try (InputStream in = Object.class.getResourceAsStream("/" + file_name);
                FileOutputStream out = new FileOutputStream(
                        new File(output_dir + "/" + file_name)))
        {
            if (in == null)
            {
                System.out.println(String.format("/%s not found", file_name));
                return;
            }
            byte[] b = new byte[in.available()];
            in.read(b);
            out.write(b);
        }
    }

    private void text() throws Exception
    {
        System.out.println("text");
        System.out.println();

        String file_name = "test.xml";
        ArrayList<String> lines = new ArrayList<>();

        BufferedReader reader = null;
        try
        {
            // 读取指定字符集的文本文件，FileReader使用缺省字符集
            // reader = new BufferedReader(new FileReader(dir + "/"
            // + file_name));
            reader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(output_dir + "/" + file_name),
                    "UTF-8"));
            StringBuilder sbuilder = new StringBuilder();
            String line;
            String content;
            while ((line = reader.readLine()) != null)
            {
                // content+=line.trim(); // 极耗时
                sbuilder.append(line);
                sbuilder.append("\n");
                lines.add(line);
            }
            reader.close();
            content = sbuilder.toString();
            System.out.println(String.format("read %s len:%d lines:%d",
                    file_name, content.length(), lines.size()));
        }
        catch (Exception e)
        {
            System.err.println(String.format("read %s fail: %s", file_name, e));
            return;
        }
        finally
        {
            if (reader != null)
            {
                reader.close();
            }
        }

        String dupname = file_name.substring(0, file_name.indexOf(".xml"))
                + "-2.xml";
        BufferedWriter writer = null;
        try
        {

            writer = new BufferedWriter(
                    new FileWriter(output_dir + "/" + dupname));
            for (String line : lines)
            {
                writer.write(line);
                writer.write("\n");
            }
            System.out.println(String.format("write to %s lines:%d", dupname,
                    lines.size()));
        }
        catch (Exception e)
        {
            System.err.println(String.format("write %s fail: %s", dupname, e));
            return;
        }
        finally
        {
            if (writer != null)
            {
                writer.close();
            }
        }
    }

    private void stream() throws Exception
    {
        System.out.println("stream");
        System.out.println();

        String file_name = "test.jpg";
        byte[] binary;

        FileInputStream file_in = null;
        try
        {
            File file = new File(output_dir + "/" + file_name);
            System.out.println(String.format("file:%s len:%d", file.getPath(),
                    file.length()));
            file_in = new FileInputStream(file);
            System.out.println(String.format("file:%s stream.available:%d",
                    file_name, file_in.available()));
            binary = new byte[(int) file.length()];
            file_in.read(binary);
            System.out.println(
                    String.format("read %s len:%d", file_name, binary.length));

            // String
            // long_file_name="/home/arron/视频/Snowpiercer.2013.720p_雪国列车/Snowpiercer.2013.720p.BluRay.x264.DTS-WiKi.mkv";
            // File long_file=new File(long_file_name);
            // FileInputStream long_file_in=new FileInputStream(long_file);
            // System.out.println(String.format(
            // "%s.%s: file:%s length:%d stream.available:%d",
            // __CLASS__, __METHOD__, long_file_name,
            // long_file.length(), long_file_in.available()));
            // long_file_in.close();
        }
        catch (Exception e)
        {
            System.err.println(String.format("read %s fail: %s", e));
            return;
        }
        finally
        {
            if (file_in != null)
            {
                file_in.close();
            }
        }

        String dupname = file_name.substring(0, file_name.indexOf(".jpg"))
                + "-2.jpg";
        FileOutputStream file_out = null;
        try
        {
            file_out = new FileOutputStream(output_dir + "/" + dupname);
            file_out.write(binary);
        }
        catch (Exception e)
        {
            System.err.println(String.format("write %s fail: %s", e));
            return;
        }
        finally
        {
            if (file_out != null)
            {
                file_out.close();
            }
        }
    }

    private void performance() throws Exception
    {
        System.out.println("performance");
        System.out.println();

        String dir = "_performance";
        init_dir(dir);

        String filename = "test-100k";
        InputStream in = null;
        String s;
        try
        {
            in = this.getClass()
                    .getResourceAsStream(String.format("/%s.xml", filename));
            byte[] buf = new byte[(int) in.available()];
            in.read(buf);
            s = new String(buf);
        }
        finally
        {
            if (in != null)
                in.close();
        }

        long begin_time = Instant.now().toEpochMilli();
        int num = 2000;
        for (int i = 0; i < num; i++)
        {
            BufferedWriter writer = null;
            try
            {

                writer = new BufferedWriter(new FileWriter(
                        String.format("%s/%s-%d.xml", dir, filename, i)));
                writer.write(s);
            }
            finally
            {
                if (writer != null)
                {
                    writer.close();
                }
            }
        }
        System.out.println(String.format("write %d file, cost %d ms", num,
                Instant.now().toEpochMilli() - begin_time));
    }
}
